package com.founder.gateway.component.transport.netty.extension.support;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import com.founder.gateway.system.consts.ApiSetuErrorCode;
import io.netty.handler.codec.http.HttpHeaderNames;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpOptions;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpTrace;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.setu.framework.util.SetuApplicationUtil;

import com.founder.gateway.component.transport.netty.exception.NettyException;
import com.founder.gateway.component.transport.netty.filter.NettyFilterChain;
import com.founder.gateway.component.transport.netty.http.NettyHttpRequest;
import com.founder.gateway.component.transport.netty.http.NettyHttpResponse;
import com.founder.gateway.system.util.HttpNormUtil;

import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;

public class RequestNettyHttpFilter extends AbstractNettyHttpFilter {
    @Override
    public void doFilter(NettyHttpRequest request, NettyHttpResponse response, NettyFilterChain chain) throws IOException, NettyException {
        sendRequest(request, response, chain);
        chain.doFilter(request, response);
    }

    // 发送请求到目标服务
    private void sendRequest(NettyHttpRequest request, NettyHttpResponse response, NettyFilterChain chain) throws IOException, NettyException {
        String uri = request.uri();
        String method = chain.getApiEntityEntity().getMethod();
        HttpRequestBase httpRequest;
        if (HttpMethod.OPTIONS.name().equalsIgnoreCase(method)) {
            httpRequest = new HttpOptions(uri);
        } else if (HttpMethod.GET.name().equalsIgnoreCase(method)) {
            httpRequest = new HttpGet(uri);
        } else if (HttpMethod.HEAD.name().equalsIgnoreCase(method)) {
            httpRequest = new HttpHead(uri);
        } else if (HttpMethod.POST.name().equalsIgnoreCase(method)) {
            httpRequest = new HttpPost(uri);
        } else if (HttpMethod.PUT.name().equalsIgnoreCase(method)) {
            httpRequest = new HttpPut(uri);
        } else if (HttpMethod.PATCH.name().equalsIgnoreCase(method)) {
            httpRequest = new HttpPatch(uri);
        } else if (HttpMethod.DELETE.name().equalsIgnoreCase(method)) {
            httpRequest = new HttpDelete(uri);
        } else if (HttpMethod.TRACE.name().equalsIgnoreCase(method)) {
            httpRequest = new HttpTrace(uri);
        } else {
            throw new NettyException(ApiSetuErrorCode.API_REQUEST_UNSUPPORTED);
        }

        // 公共配置
        httpRequest.setConfig(SetuApplicationUtil.getBean(RequestConfig.class));

        String[] ignoreHeaders = {"host", "transfer-encoding", "content-length", "cookie"};
        // 设置 request header
        HttpHeaders headers = request.headers();
        for (String name : headers.names()) {
            if (!name.startsWith(HttpNormUtil.HEADER_FOUNDER) && Arrays.stream(ignoreHeaders).noneMatch(header -> header.equalsIgnoreCase(name))) {
                httpRequest.addHeader(name, headers.get(name));
            }
        }

        // Cookie 处理
        List<String> cookies = headers.getAll("cookie");
        if (cookies != null && !cookies.isEmpty()) {
            httpRequest.addHeader("Cookie", String.join(";", cookies));
        }

        // 设置 request body
        if (httpRequest instanceof HttpEntityEnclosingRequest) {
            byte[] body;
            ByteBuf byteBuf = request.content();
            if (byteBuf != null) {
                body = new byte[byteBuf.readableBytes()];
                byteBuf.getBytes(0, body);
                ((HttpEntityEnclosingRequest) httpRequest).setEntity(new ByteArrayEntity(body));
            }
        }

        // 请求
        HttpResponse httpResponse = SetuApplicationUtil.getBean(CloseableHttpClient.class).execute(httpRequest);

        // 设置 response header
        for (Header header : httpResponse.getAllHeaders()) {
            response.headers().set(header.getName(), header.getValue());
        }
        response.headers().remove(HttpHeaderNames.TRANSFER_ENCODING);

        // 设置 response body
        HttpEntity entity = httpResponse.getEntity();
        if (entity != null) {
            response.setContent(EntityUtils.toByteArray(entity));
        }
    }
}
